﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.ExtensibleStorage;
using Autodesk.Revit.UI;
using YArchitech.Controls;
using YArchitech.ProgressBar;
using YJKCodeBase.WinForm;
using YJKView;

namespace ModelChecking.ModelValidation.AdjoinFireZone
{
	public class AdjoinFireZoneCheck
	{
        public AdjoinFireZoneCheck(ExternalCommandData cmdData, bool bIsHorViewPlan, WindowHandle hWndRevit)
		{
			this.m_cmdData = cmdData;
			this.m_doc = cmdData.Application.ActiveUIDocument.Document;
			this.m_bIsHorViewPlan = bIsHorViewPlan;
			this.m_uiApp = cmdData.Application;
			this.m_hWndRevit = hWndRevit;
		}

		public bool CheckHorViewPlan()
		{
			return AdjoinFireZoneCheck.ManageHorCheckInfo(ref this.m_lstCheckInfoHor, this.m_lstViewPlan, this.m_uiApp, this.m_hWndRevit);
		}

		public bool CheckVerViewPlan()
		{
			return AdjoinFireZoneCheck.ManageVerCheckInfo(ref this.m_lstCheckInfoVer, this.m_dictPairPlan, this.m_uiApp, this.m_bSetSprinkler, this.m_hWndRevit);
		}

        public static bool ManageHorCheckInfo(ref List<CheckPairWinDoorHorInfo> lstCheckInfo, List<ViewPlan> lstViewPlan, UIApplication uiApp, WindowHandle hWndRevit)
		{
			Document document = uiApp.ActiveUIDocument.Document;
			lstCheckInfo.Clear();
			ProgressBarForm progressBarForm = new ProgressBarForm(lstViewPlan.Count + 1, ProgressBarStyle.Blocks, true);
			progressBarForm.Show(hWndRevit);
			progressBarForm.RefreshProgressBar();
			foreach (ViewPlan viewPlan in lstViewPlan)
			{
				FindCrossPointsHorFireZone findCrossPointsHorFireZone = new FindCrossPointsHorFireZone(document, viewPlan, uiApp);
				if (!findCrossPointsHorFireZone.ManageCurViewPlanCrossPoints())
				{
					progressBarForm.RefreshProgressBar();
				}
				else
				{
					List<Wall> outWalls = findCrossPointsHorFireZone.GetOutWalls();
					Dictionary<XYZ, XYZ> crossPoints = findCrossPointsHorFireZone.GetCrossPoints();
					CheckPointManage checkPointManage = new CheckPointManage(document, viewPlan, outWalls, crossPoints, hWndRevit);
					if (!checkPointManage.CheckPairDoorWinTol())
					{
						progressBarForm.RefreshProgressBar();
					}
					else
					{
						lstCheckInfo.AddRange(checkPointManage.GetCheckResult());
						if (progressBarForm.m_stopTag)
						{
							return false;
						}
						progressBarForm.RefreshProgressBar();
					}
				}
			}
			for (int i = 0; i < lstCheckInfo.Count; i++)
			{
				if (AdjoinFireZoneCheck.IsPairDoorWinData(lstCheckInfo[i].m_eleWinDoor1, lstCheckInfo[i].m_eleWinDoor2))
				{
					lstCheckInfo.RemoveAt(i);
					i--;
				}
			}
			return lstCheckInfo.Count != 0;
		}

		private static bool IsExistInPlanDict(ref List<FindWinDoorVerInfo> lstWinDoorInfo, ViewPlan curViewPlan, Dictionary<ViewPlan, List<FindWinDoorVerInfo>> dictPlanWinDoorList)
		{
			foreach (KeyValuePair<ViewPlan, List<FindWinDoorVerInfo>> keyValuePair in dictPlanWinDoorList)
			{
				if (curViewPlan.Id == keyValuePair.Key.Id)
				{
					lstWinDoorInfo = keyValuePair.Value;
					return true;
				}
			}
			return false;
		}

        public static bool ManageVerCheckInfo(ref List<CheckPairWinDoorVerInfo> lstCheckInfo, Dictionary<ViewPlan, ViewPlan> dictPairPlan, UIApplication uiApp, bool bSetSprinkler, WindowHandle hWndRevit)
		{
			Document document = uiApp.ActiveUIDocument.Document;
			lstCheckInfo.Clear();
			Dictionary<ViewPlan, List<FindWinDoorVerInfo>> dictionary = new Dictionary<ViewPlan, List<FindWinDoorVerInfo>>();
			ProgressBarForm progressBarForm = new ProgressBarForm(dictPairPlan.Count + 1, ProgressBarStyle.Blocks, true);
			progressBarForm.Show(hWndRevit);
			progressBarForm.RefreshProgressBar();
			foreach (KeyValuePair<ViewPlan, ViewPlan> keyValuePair in dictPairPlan)
			{
				List<FindWinDoorVerInfo> list = new List<FindWinDoorVerInfo>();
				if (!AdjoinFireZoneCheck.IsExistInPlanDict(ref list, keyValuePair.Key, dictionary))
				{
					if (!FireZoneVerWindowManage.GetDoorWinTolInfo(ref list, keyValuePair.Key, uiApp))
					{
						progressBarForm.RefreshProgressBar();
						continue;
					}
					dictionary.Add(keyValuePair.Key, list);
				}
				List<FindWinDoorVerInfo> list2 = new List<FindWinDoorVerInfo>();
				if (!AdjoinFireZoneCheck.IsExistInPlanDict(ref list2, keyValuePair.Value, dictionary))
				{
					if (!FireZoneVerWindowManage.GetDoorWinTolInfo(ref list2, keyValuePair.Value, uiApp))
					{
						progressBarForm.RefreshProgressBar();
						continue;
					}
					dictionary.Add(keyValuePair.Value, list2);
				}
				List<CheckPairWinDoorVerInfo> list3 = new List<CheckPairWinDoorVerInfo>();
				AdjoinFireZoneCheck.ManageVerCheckInfoByUpDown(ref list3, list, list2, bSetSprinkler, hWndRevit);
				if (list3.Count > 0)
				{
					lstCheckInfo.AddRange(list3);
				}
				if (progressBarForm.m_stopTag)
				{
					return false;
				}
				progressBarForm.RefreshProgressBar();
			}
			for (int i = 0; i < lstCheckInfo.Count; i++)
			{
				if (AdjoinFireZoneCheck.IsPairDoorWinData(lstCheckInfo[i].m_eleWinDoor1, lstCheckInfo[i].m_eleWinDoor2))
				{
					lstCheckInfo.RemoveAt(i);
					i--;
				}
			}
			return lstCheckInfo.Count != 0;
		}

        public static void ManageVerCheckInfoByUpDown(ref List<CheckPairWinDoorVerInfo> lstCheckInfo, List<FindWinDoorVerInfo> lstWinDoorInfUp, List<FindWinDoorVerInfo> lstWinDoorInfoBottom, bool bSetSprinkler, WindowHandle hWndRevit)
		{
			foreach (FindWinDoorVerInfo doorWinInfoDown in lstWinDoorInfUp)
			{
				foreach (FindWinDoorVerInfo doorWinInfoUp in lstWinDoorInfoBottom)
				{
					CheckPairWinDoorVerInfo item = new CheckPairWinDoorVerInfo();
					if (FireZoneVerWindowManage.IsDoorWinVerAdjoin(ref item, doorWinInfoUp, doorWinInfoDown, bSetSprinkler))
					{
						lstCheckInfo.Add(item);
					}
				}
			}
		}

		public bool GetTolViewPlan()
		{
			List<ViewPlan> allFireAreaViewPlan = FloorSelectManager.GetAllFireAreaViewPlan(this.m_doc);
			SelectFireZoneFloorForm selectFireZoneFloorForm = new SelectFireZoneFloorForm(allFireAreaViewPlan, this.m_doc, this.m_bIsHorViewPlan);
			if (selectFireZoneFloorForm.ShowDialog() != DialogResult.OK)
			{
				return false;
			}
			foreach (int index in selectFireZoneFloorForm.SelectedViewIndexs())
			{
				this.m_lstViewPlan.Add(allFireAreaViewPlan[index]);
			}
			if (!this.m_bIsHorViewPlan)
			{
				this.m_dictPairPlan = selectFireZoneFloorForm.m_dictPairPlan;
			}
			return true;
		}

		public bool SelectSetSprinkler()
		{
			SprinklerInfoForm sprinklerInfoForm = new SprinklerInfoForm();
			if (sprinklerInfoForm.ShowDialog() != DialogResult.OK)
			{
				return false;
			}
			this.m_bSetSprinkler = sprinklerInfoForm.m_bSetSprinkler;
			return true;
		}

		public void SetTrustInfo()
		{
			bool flag = false;
			Transaction transaction = new Transaction(this.m_doc);
			transaction.Start("SetTrust");
			if (this.m_bIsHorViewPlan)
			{
				using (List<CheckPairWinDoorHorInfo>.Enumerator enumerator = this.m_lstCheckInfoHor.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						CheckPairWinDoorHorInfo checkPairWinDoorHorInfo = enumerator.Current;
						if (checkPairWinDoorHorInfo.m_bIsTrust)
						{
							AdjoinFireZoneCheck.WritePairDoorWinData(checkPairWinDoorHorInfo.m_eleWinDoor1, checkPairWinDoorHorInfo.m_eleWinDoor2);
							if (!flag)
							{
								flag = checkPairWinDoorHorInfo.IsLinkedElement();
							}
						}
					}
					goto IL_C8;
				}
			}
			foreach (CheckPairWinDoorVerInfo checkPairWinDoorVerInfo in this.m_lstCheckInfoVer)
			{
				if (checkPairWinDoorVerInfo.m_bIsTrust)
				{
					AdjoinFireZoneCheck.WritePairDoorWinData(checkPairWinDoorVerInfo.m_eleWinDoor1, checkPairWinDoorVerInfo.m_eleWinDoor2);
					if (!flag)
					{
						flag = checkPairWinDoorVerInfo.IsLinkedElement();
					}
				}
			}
			IL_C8:
			transaction.Commit();
			if (flag)
			{
				YJKMessageBox.Show("链接文件中的门窗不设置信任关系");
			}
		}

		public static void WritePairDoorWinData(Element eleDoorWinCur, Element eleDoorWinOther)
		{
			if (!eleDoorWinCur.Document.IsLinked)
			{
				List<ElementId> list = AdjoinFireZoneCheck.ReadPairData(eleDoorWinCur);
				if (list == null)
				{
					list = new List<ElementId>();
				}
				if (list.IndexOf(eleDoorWinOther.Id) < 0)
				{
					list.Add(eleDoorWinOther.Id);
					AdjoinFireZoneCheck.WritePairData(eleDoorWinCur, list);
				}
			}
			if (!eleDoorWinOther.Document.IsLinked)
			{
				List<ElementId> list2 = AdjoinFireZoneCheck.ReadPairData(eleDoorWinOther);
				if (list2 == null)
				{
					list2 = new List<ElementId>();
				}
				if (list2.IndexOf(eleDoorWinCur.Id) < 0)
				{
					list2.Add(eleDoorWinCur.Id);
					AdjoinFireZoneCheck.WritePairData(eleDoorWinOther, list2);
				}
			}
		}

		public static void DeletePairDoorWinTrustInfo(Element eleDoorWinCur, Element eleDoorWinOther, Document doc)
		{
			Transaction transaction = new Transaction(doc);
			transaction.Start("DeleteTrust");
			if (!eleDoorWinCur.Document.IsLinked)
			{
				List<ElementId> list = AdjoinFireZoneCheck.ReadPairData(eleDoorWinCur);
				if (list == null)
				{
					list = new List<ElementId>();
				}
				if (list.IndexOf(eleDoorWinOther.Id) >= 0)
				{
					list.Remove(eleDoorWinOther.Id);
					AdjoinFireZoneCheck.WritePairData(eleDoorWinCur, list);
				}
			}
			if (!eleDoorWinOther.Document.IsLinked)
			{
				List<ElementId> list2 = AdjoinFireZoneCheck.ReadPairData(eleDoorWinOther);
				if (list2 == null)
				{
					list2 = new List<ElementId>();
				}
				if (list2.IndexOf(eleDoorWinCur.Id) >= 0)
				{
					list2.Remove(eleDoorWinCur.Id);
					AdjoinFireZoneCheck.WritePairData(eleDoorWinOther, list2);
				}
			}
			transaction.Commit();
		}

		public static bool IsPairDoorWinData(Element eleDoorWinCur, Element eleDoorWinOther)
		{
			if (eleDoorWinCur.Document.IsLinked && eleDoorWinOther.Document.IsLinked)
			{
				return false;
			}
			List<ElementId> list = AdjoinFireZoneCheck.ReadPairData(eleDoorWinCur);
			List<ElementId> list2 = AdjoinFireZoneCheck.ReadPairData(eleDoorWinOther);
			return (list != null && list.IndexOf(eleDoorWinOther.Id) >= 0) || (list2 != null && list2.IndexOf(eleDoorWinCur.Id) >= 0);
		}

		public static void WritePairData(Element eleDoorWin, List<ElementId> lstEleIdAdjoinDoorWin)
		{
			Guid guid = new Guid(AdjoinFireZoneCheck.m_GuidCheck);
			Schema schema = Schema.Lookup(guid);
			if (schema == null)
			{
				SchemaBuilder schemaBuilder = new SchemaBuilder(guid);
				schemaBuilder.SetSchemaName("AdjoinDoorWinId_XData");
				schemaBuilder.AddArrayField(AdjoinFireZoneCheck.m_strFireld, typeof(ElementId));
				schema = schemaBuilder.Finish();
			}
			Entity entity = new Entity(schema);
			Field field = schema.GetField(AdjoinFireZoneCheck.m_strFireld);
			entity.Set<IList<ElementId>>(field, lstEleIdAdjoinDoorWin);
			eleDoorWin.SetEntity(entity);
		}

		public static List<ElementId> ReadPairData(Element element)
		{
			try
			{
				Guid guid = new Guid(AdjoinFireZoneCheck.m_GuidCheck);
				Schema schema = Schema.Lookup(guid);
				if (schema != null)
				{
					Entity entity = element.GetEntity(schema);
					if (entity != null && entity.Schema != null)
					{
						Field field = schema.GetField(AdjoinFireZoneCheck.m_strFireld);
						return entity.Get<IList<ElementId>>(field).ToList<ElementId>();
					}
				}
			}
			catch
			{
			}
			return null;
		}

		private ExternalCommandData m_cmdData;

		private Document m_doc;

		private UIApplication m_uiApp;

		private WindowHandle m_hWndRevit;

		private List<ViewPlan> m_lstViewPlan = new List<ViewPlan>();

		private Dictionary<ViewPlan, ViewPlan> m_dictPairPlan = new Dictionary<ViewPlan, ViewPlan>();

		public List<CheckPairWinDoorHorInfo> m_lstCheckInfoHor = new List<CheckPairWinDoorHorInfo>();

		public List<CheckPairWinDoorVerInfo> m_lstCheckInfoVer = new List<CheckPairWinDoorVerInfo>();

		public bool m_bIsHorViewPlan = true;

		public bool m_bSetSprinkler = true;

		private static string m_GuidCheck = "9D90F865-3C24-24F0-75F4-45E64073F146";

		private static string m_strFireld = "AdjoinDoorWin";
	}
}
